import "./TEditor.css";
import HTML from "./TEditor.json";
import React, { Component} from "react";
import ReactDOM from 'react-dom'
import TestCodeMirror from './TestCodeMirror'
import PubSub from "pubsub-js";




var ServerModules = HTML.moudles.map((item,key)=>`<script type="moudle" src=${item.url}></script>`);
var snippets = [{focus: 0,key: 0,codeString :'console.log(\'test\')'}]
var blockNum = 0 
//focus是插入的位置也即block的实际位置 不能用此与id和key关联
//blockNum代表block的唯一id和key key再重新渲染时起作用
const languageMap = ['javascript','clike','xml','sql']
function toHtml(code)
{ 
  
  var _htmlString = `<!DOCTYPE html> <html lang="en">
  <head>
    ${HTML.head}
    <base href="t-library/" target="_blank">
  </head>
  <body>
  <script src="libs/TConsole.js" type="text/javascript" defer="defer"> </script>
  `;
  
  ServerModules.forEach(element => {
    _htmlString+=element
  });

  _htmlString+=`<script type="module">
  import TestModule from "./libs/TestModule.js";
  ${code}
  </script>
  <div id="root" style="display: flex; flex-direction: column;"></div>
  </body>
</html>`;

  return _htmlString;
}

class TCodeEidtor extends Component{
  constructor(props){
    super(props);
    this.state={
      codeString:props.value,
      language :'javascript'
    }
    this.refIframe = React.createRef();
    this.code = {
      value : 'console.log(\'test\')',
      focus : `${this.props.uid}`
    }
  }


  subscribeCode= ()=>{
    this.token = PubSub.subscribe(`${this.props.uid}`, (_,data)=>{
      this.code = {
        value : data,
        focus : `${this.props.uid}`
      }
      ReactDOM.unmountComponentAtNode(document.getElementById(`${this.props.uid}`))
      ReactDOM.render(
        <TestCodeMirror handleChange = {this.handleChange}  value={data}   language={'javascript'} uid = {this.props.uid} onFocus={this.props.onFocus}></TestCodeMirror>,document.getElementById(`${this.props.uid}`)
      )
    });
  }

  componentDidMount(){
    this.showTestCodeMirror()
    this.subscribeCode()
  }

  componentWillUnmount(){
  }

  handleFocus =()=>{
    this.props.focus(this.props.index);
  }
  
  handleChange = (value,focus) =>{
    this.code = {
      value : value,
      focus : focus
    }
    console.log(this.code);
  }

  

  newCodeBlock()
  {
    this.props.newCodeBlock(this.props.index);
  }

  delCodeBlock()
  {
    this.props.delCodeBlock(this.props.index);
  }

  clearCode(){
    ReactDOM.unmountComponentAtNode(document.getElementById(`${this.props.uid}`))
    ReactDOM.render(
      <TestCodeMirror handleChange = {this.handleChange}  value={''}   language={'javascript'} uid = {this.props.uid} onFocus={this.props.onFocus}></TestCodeMirror>,document.getElementById(`${this.props.uid}`)
    )
  }

  toScript(code){
    // var scriptString = `<script type="module">`;
    // scriptString += this.state.codeString;
    // scriptString += `</script>`;
    return code;// scriptString;
  }

  runCode(){
    var doc = toHtml(this.toScript(this.code.value));
    this.refIframe.current.srcdoc = doc
    
  }

  showTestCodeMirror =()=>{
    //ReactDOM.unmountComponentAtNode(document.getElementById(`${this.props.uid}`))
    if(document.getElementById(`${this.props.uid}`)!=null)
      import (`../codemirror/mode/${this.state.language}/${this.state.language}.js`).then(
      ReactDOM.render(
        <TestCodeMirror handleChange = {this.handleChange}  value={this.props.value}   language={'javascript'} uid = {this.props.uid} onFocus={this.props.onFocus}></TestCodeMirror>,document.getElementById(`${this.props.uid}`)
      )
      )
  }

  handleLanguageChange = (e) =>{
    var CM = document.getElementById('TestCodeMirror')
    if(typeof(CM) =="undefined")
    {

    }else{
      console.log('ss');
      ReactDOM.unmountComponentAtNode(CM)
    }
    this.setState({
      language: e.target.value
    },()=>{console.log(this.state.language);})
  }

 

  render(){
    return(
     
      <div className="e-code">
        {/* <textarea value={this.props.value} onChange={this.handleValueChanged} onFocus={this.handleFocus.bind(this)}>编写区</textarea> */}
        <div id = {this.props.uid} ></div>
        {/* <TestCodeMirror value={this.props.value} onChange={this.handleValueChanged } onFocus={this.handleFocus}></TestCodeMirror> */}
        <div className="e-action">
          <select id = 'languageMap' onChange={this.handleLanguageChange}>
            {languageMap.map((item,index)=>{
              return <option key={item} id={item}>{item}</option>
            })}
          </select>
          <button onClick={this.runCode.bind(this)}>运行</button>
          <button onClick={this.clearCode.bind(this)}>重置</button>
          <button onClick={this.delCodeBlock.bind(this)}>删除</button>
          <button onClick={this.newCodeBlock.bind(this)}>新建</button>
        </div>
        <iframe title={this.props.uid} className="e-result" ref={this.refIframe}
        ></iframe>
      </div>
    );
  }
}

export default
class TEditor extends Component{
  constructor(props)
  {
    super(props);
    this.state={
      snippets: [],
      focus   : -1,
      appendCode :'',
      codeList :[]
    }
    this.srcDiv = React.createRef();
  }
  
  componentDidMount(){
    this.setState({
      snippets : [`console.log("log");\r\nconsole.warn("warn");\r\nconsole.error("error");`],
      focus    : 0,
    });

  }
  
  backspace(){
    this.props.home();
  }

  newCodeBlock(uid){
    blockNum++
    snippets.splice(parseInt(uid)+1, 0,{focus:parseInt(uid)+1, key:blockNum ,codeString:'console.log("test")'});
    this.forceUpdate()
  }

  delCodeBlock(uid){
    if(snippets.length === 1) return; // 至少有一个代码块存在
    snippets.splice(parseInt(uid), 1);
    this.forceUpdate()
  }

  updateValue(uid, value){
    var snippets = this.state.snippets;
    snippets[parseInt(uid)] = value;
    this.setState({snippets:snippets});
  }


  appendCode = (event) =>{
    const moudles = HTML.moudles;
    const pkg = moudles[event.target.id];
    this.setState({appendCode:`${pkg.examples}`})
    if(!document.getElementById(`${this.targetId}`)){
      alert('请选择要添加code的输入框！')
      return ;
    }  
    var value = this.codeString + this.state.appendCode
    PubSub.publish(`${this.targetId}`, value) //发布消息
    
  }

  setCodeString = () =>{

  }

  getCodeString = () =>{

  }

  _createJSLibs(){
    return HTML.moudles.map((item,key)=>
      <div key={key} className="e-module">
        <button id={key} onClick={this.appendCode.bind(this)}>{item.pkg}</button>
        <label>示例:</label>
        {item.examples.length>0?item.examples.map(
          (example,key)=><div className="div-lable" key={key}
            >{example}</div>
        ):""}
      </div>
    );
  }

  onFoucs = (id,codeString) =>{
    this.targetId = id
    this.codeString = codeString
    console.log('FocusID和codeString',id,codeString);
  }


  render(){
    return(
      <div className="editor">
        <div className="e-head"><h1>在线编辑器<button onClick={this.backspace.bind(this)}>返回</button></h1></div>
        <div className="e-menu">
          <button>导入</button>
          <button>导出</button>
        </div>
        <div className="e-body">
          <div className="e-slider">
            JS库
            {this._createJSLibs()}
          </div>
          <div className="h-drag-div"></div>
          <div className="e-content">
            {snippets.map((value, key)=>{
              return <TCodeEidtor 
              key={`text${value.key}`}
              index = {value.focus}
              uid={`text${value.key}`}
              value={value.codeString} 
              appendCode = {this.state.appendCode}
              onFocus      = {this.onFoucs}
              updateValue  = {this.updateValue.bind(this)}
              delCodeBlock = {this.delCodeBlock.bind(this)}
              newCodeBlock = {this.newCodeBlock.bind(this)}
              update       = {this.forceUpdate.bind(this)}/>
             } )
              }
          </div>
        </div>
        <div className="v-drag-div"></div>
        <div className="e-bottom" id="console">终端</div>
      </div>
    );
  }
}